---
title: Guide Documents > S/W Development Kit
---
import { Tabs } from 'nextra/components'

## Outline
<Tabs 
  items={['Configuration', 'Build Script', 'Generated SDK Library']} 
  defaultIndex={1}>
  <Tabs.Tab>
```typescript copy filename="nestia.config.ts" showLineNumbers
import { INestiaConfig } from "@nestia/sdk";
import { NestFactory } from "@nestjs/core";
// import { FastifyAdapter } from "@nestjs/platform-fastify";

import { YourModule } from "./src/YourModule";

const NESTIA_CONFIG: INestiaConfig = {
  input: async () => {
    const app = await NestFactory.create(YourModule);
    // const app = await NestFactory.create(YourModule, new FastifyAdapter());
    // app.setGlobalPrefix("api");
    // app.enableVersioning({
    //     type: VersioningType.URI,
    //     prefix: "v",
    // })
    return app;
  },
  output: "src/api",
  distribute: "packages/api",
};
export default NESTIA_CONFIG;
```
  </Tabs.Tab>
  <Tabs.Tab>
```bash filename="Terminal" showLineNumbers {}
npx nestia sdk
```
  </Tabs.Tab>
  <Tabs.Tab>
```typescript filename="src/api/functional/bbs/articles/index.ts" showLineNumbers
/**
 * Update an article.
 *
 * @param section Section code
 * @param id Target article ID
 * @param input Content to update
 * @returns Updated content
 *
 * @controller BbsArticlesController.update()
 * @path PUT /bbs/:section/articles/:id
 * @nestia Generated by Nestia - https://github.com/samchon/nestia
 */
export async function update(
  connection: IConnection,
  section: string,
  id: string & Format<"uuid">,
  input: update.Input,
): Promise<update.Output> {
  return PlainFetcher.fetch(
    {
      ...connection,
      headers: {
        ...connection.headers,
        "Content-Type": "application/json",
      },
    },
    {
      ...update.METADATA,
      path: update.path(section, id),
    } as const,
    input,
  );
}
export namespace update {
  export type Input = Primitive<IBbsArticle.IStore>;
  export type Output = Primitive<IBbsArticle>;

  export const METADATA = {
    method: "PUT",
    path: "/bbs/articles/:section/:id",
    request: {
      type: "application/json",
      encrypted: false,
    },
    response: {
      type: "application/json",
      encrypted: false,
    },
    status: null,
  } as const;

  export const path = (
    section: string,
    id: string & Format<"uuid">,
  ): string => {
    return `/bbs/articles/${encodeURIComponent(
      section ?? "null",
    )}/${encodeURIComponent(id ?? "null")}`;
  };
}
```
  </Tabs.Tab>
</Tabs>

Collection of typed `fetch` functions with DTO structures.

Configure [`nestia.config.ts`](#nestiaconfigts) file and run `npx nestia sdk` command. 

Then, `@nestia/sdk` will analyze your NestJS backend server code, and generate SDK (Software Development Kit) library composed with. The newly generated SDK library would be composed with `DTO` and `fetch` functions with type definitions following your NestJS server.

With the SDK library composed with RPC (Remote Procedure Call) functions, you can easily develop e2e test program. Also, frontend developers can utilize the SDK library to interact with your NestJS backend server, much safely and conveniently. 

If you can't imagine how the SDK library works, then look at the gif image of below. Left side is the NestJS backend server program, and right side is the Frontend program interacting with your server. Isn't it look like much more convenient and safer than before [Swagger Documents](swagger) case?

![SDK](https://user-images.githubusercontent.com/13158709/215004990-368c589d-7101-404e-b81b-fbc936382f05.gif)

> Left is NestJS server code, and right is client (frontend) code utilizing SDK




## Application Module
<Tabs items={[
  <code>nestia.config.ts</code>, 
  <code>INestiaConfig.ts</code>,
]}>
  <Tabs.Tab>
```typescript copy filename="nestia.config.ts" showLineNumbers {8-17}
import { INestiaConfig } from "@nestia/sdk";
import { NestFactory } from "@nestjs/core";
// import { FastifyAdapter } from "@nestjs/platform-fastify";

import { YourModule } from "./src/YourModule";

const NESTIA_CONFIG: INestiaConfig = {
  input: async () => {
    const app = await NestFactory.create(YourModule);
    // const app = await NestFactory.create(YourModule, new FastifyAdapter());
    // app.setGlobalPrefix("api");
    // app.enableVersioning({
    //     type: VersioningType.URI,
    //     prefix: "v",
    // })
    return app;
  },
  output: "src/api",
  distribute: "packages/api",
};
export default NESTIA_CONFIG;
```
  </Tabs.Tab>
  <Tabs.Tab>
```typescript copy filename="INestiaConfig.ts" showLineNumbers {10-29}
import type { INestApplication } from "@nestjs/common";
import type { OpenApi } from "@samchon/openapi";

/**
 * Definition for the `nestia.config.ts` file.
 *
 * @author Jeongho Nam - https://github.com/samchon
 */
export interface INestiaConfig {
  /**
   * Accessor of controller classes.
   *
   * You can specify it within two ways
   *
   *   - Asynchronous function returning `INestApplication` instance
   *   - Specify the path or directory of controller class files
   */
  input:
    | (() => Promise<INestApplication>)
    | INestiaConfig.IInput
    | string[]
    | string;

  /**
   * Output directory that SDK would be placed in.
   *
   * If not configured, you can't build the SDK library.
   */
  output?: string;

  /**
   * Building `swagger.json` is also possible.
   *
   * If not specified, you can't build the `swagger.json`.
   */
  swagger?: INestiaConfig.ISwaggerConfig;

  /**
   * Target directory that SDK distribution files would be placed in.
   *
   * If you configure this property and runs `npx nestia sdk` command,
   * distribution environments for the SDK library would be generated.
   *
   * After the SDK library generation, move to the `distribute` directory,
   * and runs `npm publish` command, then you can share SDK library with
   * other client (frontend) developers.
   *
   * Recommend to use `"packages/api"` value.
   */
  distribute?: string;

  /**
   * Allow simulation mode.
   *
   * If you configure this property to be `true`, the SDK library would be contain
   * simulation mode. In the simulation mode, the SDK library would not communicate
   * with the real backend server, but just returns random mock-up data
   * with requestion data validation.
   *
   * For reference, random mock-up data would be generated by `typia.random<T>()`
   * function.
   *
   * @default false
   */
  simulate?: boolean;

  /**
   * Target directory that e2e test functions would be placed in.
   *
   * If you configure this property and runs `npx nestia e2e` command,
   * `@nestia/sdk` will analyze your NestJS backend server code, and
   * generates e2e test functions for every API endpoints.
   *
   * If not configured, you can't run `npx nestia e2e` command.
   */
  e2e?: string;

  /**
   * Whether to use propagation mode or not.
   *
   * If being configured, interaction functions of the SDK library would
   * perform the propagation mode. The propagation mode means that never
   * throwing exception even when status code is not 200 (or 201), but just
   * returning the {@link IPropagation} typed instance, which can specify its body
   * type through discriminated union determined by status code.
   *
   * @default false
   */
  propagate?: boolean;

  /**
   * Whether to clone DTO structures or not.
   *
   * If being configured, all of DTOs used in the backend server would be cloned
   * into the `structures` directory, and the SDK library would be refer to the
   * cloned DTOs instead of the original.
   *
   * @default false
   */
  clone?: boolean;

  /**
   * Whether to wrap DTO by primitive type.
   *
   * If you don't configure this property as `false`, all of DTOs in the
   * SDK library would be automatically wrapped by {@link Primitive} type.
   *
   * For refenrece, if a DTO type be capsuled by the {@link Primitive} type,
   * all of methods in the DTO type would be automatically erased. Also, if
   * the DTO has a `toJSON()` method, the DTO type would be automatically
   * converted to return type of the `toJSON()` method.
   *
   * @default true
   */
  primitive?: boolean;

  /**
   * Whether to assert parameter types or not.
   *
   * If you configure this property to be `true`, all of the function
   * parameters of SDK library would be checked through
   * [`typia.assert<T>()` function](https://typia.io/docs/validators/assert/).
   *
   * This option would make your SDK library compilation time a little bit slower,
   * but would enahcne the type safety even in the runtime level.
   *
   * @default false
   */
  assert?: boolean;

  /**
   * Whether to optimize JSON string conversion 10x faster or not.
   *
   * If you configure this property to be `true`, the SDK library would utilize the
   * [`typia.assertStringify<T>() function`](https://github.com/samchon/typia#enhanced-json)
   * to boost up JSON serialization speed and ensure type safety.
   *
   * This option would make your SDK library compilation time a little bit slower,
   * but would enhance JSON serialization speed 10x faster. Also, it can ensure type
   * safety even in the runtime level.
   *
   * @default false
   */
  json?: boolean;
}
export namespace INestiaConfig {
  /**
   * List of files or directories to include or exclude to specifying the NestJS
   * controllers.
   */
  export interface IInput {
    /**
     * List of files or directories containing the NestJS controller classes.
     */
    include: string[];

    /**
     * List of files or directories to be excluded.
     */
    exclude?: string[];
  }

  /**
   * Building `swagger.json` is also possible.
   */
  export interface ISwaggerConfig {
    /**
     * Output path of the `swagger.json`.
     *
     * If you've configured only directory, the file name would be the `swagger.json`.
     * Otherwise you've configured the full path with file name and extension, the
     * `swagger.json` file would be renamed to it.
     */
    output: string;

    /**
     * OpenAPI version.
     *
     * If you configure this property to be `2.0` or `3.0`, the newly generated
     * `swagger.json` file would follow the specified OpenAPI version. The newly
     * generated `swagger.json` file would be downgraded from the OpenAPI v3.1
     * specification by {@link OpenApi.downgrade} method.
     *
     * @default 3.1
     */
    openapi?: "2.0" | "3.0" | "3.1";

    /**
     * API information.
     *
     * If omitted, `package.json` content would be used instead.
     */
    info?: Partial<OpenApi.IDocument.IInfo>;

    /**
     * List of server addresses.
     */
    servers?: OpenApi.IServer[];

    /**
     * Security schemes.
     *
     * When generating `swagger.json` file through `nestia`, if your controllers or
     * theirs methods have a security key which is not enrolled in here property,
     * it would be an error.
     */
    security?: Record<string, OpenApi.ISecurityScheme>;

    /**
     * List of tag names with description.
     *
     * It is possible to omit this property or skip some tag name even if
     * the tag name is used in the API routes. In that case, the tag name
     * would be used without description.
     *
     * Of course, if you've written a comment like `@tag {name} {description}`,
     * you can entirely replace this property specification.
     */
    tags?: OpenApi.IDocument.ITag[];

    /**
     * Decompose query DTO.
     *
     * If you configure this property to be `true`, the query DTO would be decomposed
     * into individual query parameters per each property. Otherwise you set it to be
     * `false`, the query DTO would be one object type which contains all of query
     * parameters.
     *
     * @default false
     */
    decompose?: boolean;

    /**
     * Operation ID generator.
     *
     * @param props Properties of the API endpoint.
     * @returns Operation ID.
     */
    operationId?(props: {
      class: string;
      function: string;
      method: "HEAD" | "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
      path: string;
    }): string;
  }
}
```
  </Tabs.Tab>
</Tabs>

Make `nestia.config.ts` file and run `npx nestia sdk` command.

At first, create `nestia.config.ts` file through `npx nestia init` command. It would be placed on the top level directory of your NestJS backend project. For reference, `tsconfig.json` file also must be placed in the top level directory, too. After creation, configure the `nestia.config.ts` file referencing above example code and type definition.

At least, you've to configure those two properties:

  - `input`: Accessor of controller classes
  - `output`: Path of output directory for SDK library

When you've completed above configuration, just run `npx nestia sdk` command. Then, SDK library would be newly generated, and placed into the `$config.output` directory following your `nestia.config.ts` configuration.




## Clone Mode
<Tabs items={[
  <code>nestia.config.ts</code>,
  "Source Controller",
  "Cloned DTO types"
]}>
  <Tabs.Tab>
```typescript copy filename="nestia.config.ts" showLineNumbers {19}
import { INestiaConfig } from "@nestia/sdk";
import { NestFactory } from "@nestjs/core";
// import { FastifyAdapter } from "@nestjs/platform-fastify";
 
import { YourModule } from "./src/YourModule";
 
const NESTIA_CONFIG: INestiaConfig = {
  input: async () => {
    const app = await NestFactory.create(YourModule);
    // const app = await NestFactory.create(YourModule, new FastifyAdapter());
    // app.setGlobalPrefix("api");
    // app.enableVersioning({
    //     type: VersioningType.URI,
    //     prefix: "v",
    // })
    return app;
  },
  output: "src/api",
  clone: true,
  distribute: "packages/api",
};
export default NESTIA_CONFIG;
```
  </Tabs.Tab>
  <Tabs.Tab>
```typescript showLineNumbers
import core from "@nestia/core";
import { Controller } from "@nestjs/common";
import typia, { tags } from "typia";

@Controller("bbs/articles/:section")
export class TypedBodyControlleer {
  @core.TypedRoute.Get()
  public async index(
    @core.TypedParam("section") section: string,
    @core.TypedQuery() query: IPage.IRequest,
  ): Promise<IPage<IBbsArticle.ISummary>> {
    const limit: number = query.limit ?? 100;
    const current: number = query.page ?? 1;
    const records: number = limit * (current + 3) + 5;

    return {
      pagination: {
        current,
        limit,
        records,
        pages: Math.ceil(records / limit),
      },
      data: new Array(limit).fill("").map(() => ({
        ...typia.random<IBbsArticle.ISummary>(),
        section,
      })),
    };
  }
}
interface IPage<T> {
  data: T[];
  pagination: IPage.IPagination;
}
namespace IPage {
  export interface IRequest {
    page?: null | (number & tags.Type<"uint32">);
    limit?: null | (number & tags.Type<"uint32">);
  }
  export interface IPagination {
    current: number & tags.Type<"uint32">;
    limit: number & tags.Type<"uint32">;
    records: number & tags.Type<"uint32">;
    pages: number & tags.Type<"uint32">;
  }
}

namespace IBbsArticle {
  export interface ISummary {
    id: string & tags.Format<"uuid">;
    section: string;
    writer: string;
    title: string & tags.MinLength<3> & tags.MaxLength<50>;
    created_at: string & tags.Format<"date-time">;
    /**
     * @format date-time
     */
    updated_at: string;
  }
}
```
  </Tabs.Tab>
  <Tabs.Tab>
```typescript showLineNumbers
export namespace IPageIBbsArticle {
  export type ISummary = {
    data: IBbsArticle.ISummary[];
    pagination: IPage.IPagination;
  };
}
export namespace IPage {
  export type IRequest = {
    page?: null | undefined | (number & Type<"uint32">);
    limit?: null | undefined | (number & Type<"uint32">);
  };
  export type IPagination = {
    current: number & Type<"uint32">;
    limit: number & Type<"uint32">;
    records: number & Type<"uint32">;
    pages: number & Type<"uint32">;
  };
}

export namespace IBbsArticle {
  export type ISummary = {
    id: string & Format<"uuid">;
    section: string;
    writer: string;
    title: string & MinLength<3> & MaxLength<50>;
    created_at: string & Format<"date-time">;
    updated_at: string & Format<"date-time">;
  };
}
```
  </Tabs.Tab>
</Tabs>

If you configure `clone` property to be `true` in the `nestia.config.ts` file, all of DTO structures used in the backend server would be cloned into the `structures` directory, and the SDK library would be refer to the cloned DTO structures instead of the original.

This `clone` mode is useful when you'd not separated DTO structures from the ORM models. When you're using `TypeORM` or `Prisma`, and returning the ORM generated instance directly in the controller without independent DTO structure definition, your SDK library requires the `TypeORM` or `Prisma` dependency install. By the dependency, client (frontend) developers may install the ORM library that they never need. 

In that case, it would better to remove the dependency by using this `clone` mode.




## Propagation Mode
<Tabs items={[
  <code>nestia.config.ts</code>, 
  <code>IPropagation.ts</code>,
]}>
  <Tabs.Tab>
```typescript copy filename="nestia.config.ts" showLineNumbers {19}
import { INestiaConfig } from "@nestia/sdk";
import { NestFactory } from "@nestjs/core";
// import { FastifyAdapter } from "@nestjs/platform-fastify";

import { YourModule } from "./src/YourModule";

const config: INestiaConfig = {
  input: async () => {
    const app = await NestFactory.create(YourModule);
    // const app = await NestFactory.create(YourModule, new FastifyAdapter());
    // app.setGlobalPrefix("api");
    // app.enableVersioning({
    //     type: VersioningType.URI,
    //     prefix: "v",
    // })
    return app;
  },
  output: "src/api",
  propagate: true,
  distribute: "packages/api",
};
export default config;
```
  </Tabs.Tab>
  <Tabs.Tab>
```typescript filename="IPropagation.ts" showLineNumbers
import { Primitive } from "./Primitive";

/**
 * Propagation type.
 *
 * `IPropagation` is a type gathering all possible status codes and their body
 * data types as a discriminated union type. You can specify the status code and
 * its body data type just by using conditional statement like below.
 *
 * ```typescript
 * type Output = IPropagation<{
 *    200: ISeller.IAuthorized;
 *    400: TypeGuardError.IProps;
 * >};
 *
 * const output: Output = await sdk.sellers.authenticate.join(input);
 * if (output.success) {
 *     // automatically casted to "ISeller.IAuthorized" type
 *     const authorized: ISeller.IAuthorized = output.data;
 * } else if (output.status === 400) {
 *     // automatically casted to "TypeGuardError.IProps" type
 *     const error: TypeGuardError.IProps = output.data;
 * } else {
 *     // unknown type when out of pre-defined status codes
 *     const result: unknown = output.data;
 * }
 * ```
 *
 * For reference, this `IPropagation` type is utilized by SDK library generated by
 * `@nestia/sdk`, when you've configured {@link INestiaConfig.propagate} to be `true`.
 * In that case, SDK functions generated by `@nestia/sdk` no more returns response DTO
 * typed data directly, but returns this `IPropagation` typed object instead.
 *
 * @template StatusMap Map of status code and its body data type.
 * @template Success Default success status code.
 * @author Jeongho Nam - https://github.com/samchon
 */
export type IPropagation<
  StatusMap extends {
    [P in IPropagation.Status]?: any;
  },
  Success extends number = 200 | 201,
> =
  | {
      [P in keyof StatusMap]: IPropagation.IBranch<
        P extends Success ? true : false,
        P,
        StatusMap[P]
      >;
    }[keyof StatusMap]
  | IPropagation.IBranch<false, unknown, unknown>;
export namespace IPropagation {
  /**
   * Type of configurable status codes.
   *
   * The special characters like `2XX`, `3XX`, `4XX`, `5XX` are meaning the range
   * of status codes. If `5XX` is specified, it means the status code is in the
   * range of `500` to `599`.
   */
  export type Status = number | "2XX" | "3XX" | "4XX" | "5XX";

  /**
   * Branch type of propagation.
   *
   * `IPropagation.IBranch` is a branch type composing `IPropagation` type,
   * which is gathering all possible status codes and their body data types
   * as a union type.
   */
  export interface IBranch<Success extends boolean, StatusValue, BodyData> {
    success: Success;
    status: StatusValue extends "2XX" | "3XX" | "4XX" | "5XX"
      ? StatusRange<StatusValue>
      : StatusValue extends number
      ? StatusValue
      : never;
    data: Primitive<BodyData>;
    headers: Record<string, string | string[]>;
  }

  /**
   * Range of status codes by the first digit.
   */
  export type StatusRange<T extends "2XX" | "3XX" | "4XX" | "5XX"> = T extends 0
    ? IntRange<200, 299>
    : T extends 3
    ? IntRange<300, 399>
    : T extends 4
    ? IntRange<400, 499>
    : IntRange<500, 599>;

  type IntRange<F extends number, T extends number> = Exclude<
    Enumerate<T>,
    Enumerate<F>
  >;

  type Enumerate<
    N extends number,
    Acc extends number[] = [],
  > = Acc["length"] extends N
    ? Acc[number]
    : Enumerate<N, [...Acc, Acc["length"]]>;
}
```
  </Tabs.Tab>
</Tabs>

Returns `IPropagation` typed instance instead of throwing exception.

When you configure propagate property of `nestia.config.ts` file, all of SDK functions generated by `@nestia/sdk` will perform propagation mode. The propagation mode means that never throwing exception (`HttpError`) even when response status code is not 200 (or 201), but just returning the `IPropagation` typed object, which can specify its body data type through discriminated union determined by status code.

Looking at below code tabs one by one, then you may understand exactly, what the propagation mode is. As you can see from below example code, [`@TypedException()`](../core/TypedException) decorator function can be utilized to define the failure type with specific status code. Also, if returned status code is out of pre-defined, the `IPropagation.data` type would be automatically casted to `unknown` type.

<Tabs items={[
  <code>BbsArticlesController.ts</code>,
  "Propagation Mode SDK",
  "Utilization Case",
]}>
  <Tabs.Tab>
```typescript filename="src/controllers/BbsArticlesController.ts" showLineNumbers
import core from "@nestia/core";
import { Controller } from "@nestjs/common";
import typia, { tags } from "typia";

import { IBbsArticle } from "@api/lib/structures/IBbsArticle";

@Controller("bbs/articles/:section")
export class BbsArticlesController {
  /**
   * Update an article.
   *
   * @param section Section code
   * @param id Target article ID
   * @param input Content to update
   * @returns Updated content
   */
  @core.TypedException<TypeGuardError.IProps>(400)
  @core.TypedRoute.Put(":id")
  public async update(
    @core.TypedParam("section") section: string,
    @core.TypedParam("id") id: string & tags.Format<"uuid">,
    @core.TypedBody() input: IBbsArticle.IStore,
  ): Promise<IBbsArticle> {
    return {
      ...typia.random<IBbsArticle>(),
      id,
      section,
      ...input,
    };
  }
}
```
  </Tabs.Tab>
  <Tabs.Tab>
```typescript filename="src/api/functional/bbs/articles/index.ts" showLineNumbers {19, 36-42}
/**
 * Update an article.
 *
 * @param section Section code
 * @param id Target article ID
 * @param input Content to update
 * @returns Updated content
 *
 * @controller BbsArticlesController.update()
 * @path PUT /bbs/:section/articles/:id
 * @nestia Generated by Nestia - https://github.com/samchon/nestia
 */
export async function update(
  connection: IConnection,
  section: string,
  id: string & Format<"uuid">,
  input: update.Input,
): Promise<update.Output> {
  return PlainFetcher.propagate(
    {
      ...connection,
      headers: {
        ...connection.headers,
        "Content-Type": "application/json",
      },
    },
    {
      ...update.METADATA,
      path: update.path(section, id),
    } as const,
    input,
  );
}
export namespace update {
  export type Input = Primitive<IBbsArticle.IStore>;
  export type Output = IPropagation<
    {
      200: IBbsArticle;
      400: TypeGuardError.IProps;
    },
    200
  >;

  export const METADATA = {
    method: "PUT",
    path: "/bbs/articles/:section/:id",
    request: {
      type: "application/json",
      encrypted: false,
    },
    response: {
      type: "application/json",
      encrypted: false,
    },
    status: null,
  } as const;

  export const path = (
    section: string,
    id: string & Format<"uuid">,
  ): string => {
    return `/bbs/articles/${encodeURIComponent(
      section ?? "null",
    )}/${encodeURIComponent(id ?? "null")}`;
  };
}
```
  </Tabs.Tab>
  <Tabs.Tab>
```typescript showLineNumbers
const output = await api.functional.bbs.articles.update(section, id, input);
if (output.success) {
  // automatically casted to "IBbsArticle" when status 200 (success)
  const article: IBbsArticle = output.data;
} else if (output.status === 400) {
  // casted to "TypeGuardError.IProps" when status 400
  const error: TypeGuardError.IProps = output.data;
} else {
  // casted to "unknown" when out of pre-defined status codes
  const result: unknown = output.data;
}
```
  </Tabs.Tab>
</Tabs>




## CLI Arguments
```bash filename="Terminal"
npx nestia sdk
npx nestia sdk --config nestia2.config.ts
npx nestia sdk --project tsconfig2.json
npx nestia sdk --config nestia3.config.ts --project tsconfig3.tsconfig.json
```

If you have a special configuration file that its file name is not `nestia.config.ts` or the configuration file is not placed on the root directory of the project, you can specify it with `--config` option like `npx nestia sdk --config another.config.ts`. 

Also, if you have a special `tsconfig.json` file or the project file is not located in the root directory of the project, you can specify it with `--project` argument like `npx nestia sdk --project another.tsconfig.json`, too.